package com.zzyl.service.impl;

import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.zzyl.constant.Constants;
import com.zzyl.dto.UserLoginRequestDto;
import com.zzyl.entity.Member;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.CustomerUserMapper;
import com.zzyl.service.CustomerUserService;
import com.zzyl.utils.JwtUtil;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.vo.LoginVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Service
public class CustomerUserServiceImpl implements CustomerUserService {

    @Autowired
    private CustomerUserMapper customerUserMapper;

    @Value("${zzyl.wechat.appId}")
    private String appid;

    @Value("${zzyl.wechat.appSecret}")
    private String appSecret;

    @Value("${zzyl.framework.jwt.base64-encoded-secret-key}")
    private String secretKey;

    @Value("${zzyl.framework.jwt.ttl}")
    private Integer ttl;

    /**
     * 客户信息管理
     *
     * @param dto
     * @return
     */
    @Override
    public LoginVo login(UserLoginRequestDto dto) {
        //根据code发送请求到微信，获取微信的唯一openid
        String openId = getOpenId(dto.getCode());

        //根据phonecode发送请求到微信，获取到用户手机号
        String phoneNumber = getPhoneNumber(dto.getPhoneCode(), openId);
        //根据openid查询member表，查询到了就更新手机号，没有查询到就新增一个用户
        Member member = customerUserMapper.getName(openId);
        if (null != member) {
            member.setPhone(phoneNumber);
            member.setUpdateTime(LocalDateTime.now());
            customerUserMapper.update(member);
        } else {
            member = new Member();
            String name = Constants.DEFAULT_NICKNAME_PREFIX.get((int) (Math.random() * Constants.DEFAULT_NICKNAME_PREFIX.size()));
            String substring = phoneNumber.substring(7);
            member.setName(name + substring);
            member.setPhone(phoneNumber);
            member.setOpenId(openId);
            member.setCreateTime(LocalDateTime.now());
            member.setUpdateTime(LocalDateTime.now());
            customerUserMapper.add(member);
        }
        //生成token
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", member.getId());
        claims.put("name", member.getName());
        String jwt = JwtUtil.createJWT(secretKey, ttl, claims);
        //构建返回值并返回

        LoginVo vo = new LoginVo();
        vo.setNickName(member.getName());
        vo.setToken(jwt);
        return vo;

    }

    private String getPhoneNumber(String phoneCode, String openId) {
        //获取access_token
        String accessToken = getAccessToken();
        Map<String, Object> params = new HashMap<>();
        params.put("code", phoneCode);
        params.put("openid", openId);
        HttpResponse response = HttpUtil.createPost(Constants.WX_PHONE_URL + accessToken).body(JSONUtil.toJsonStr(params)).execute();
        String json = response.body();
        if (ObjectUtil.isNotEmpty(json)) {
            JSONObject jsonObject = JSONUtil.parseObj(json);
            if (jsonObject.getInt("errcode").equals(0)) {
                JSONObject phone_info = jsonObject.getJSONObject("phone_info");
                String phoneNumber = phone_info.getStr("phoneNumber");
                return phoneNumber;
            } else {
                throw new BaseException(BasicEnum.GET_PHONE_ERROR);
            }
        } else {
            throw new BaseException(BasicEnum.GET_PHONE_ERROR);
        }
    }

    private String getAccessToken() {
        Map<String, Object> params = new HashMap<>();
        params.put("grant_type", "client_credential");
        params.put("appid", appid);
        params.put("secret", appSecret);
        HttpResponse response = HttpUtil.createGet(Constants.WX_TOKEN_URL).form(params).execute();
        String json = response.body();
        if (ObjectUtil.isNotEmpty(json)) {
            JSONObject jsonObject = JSONUtil.parseObj(json);
            if (ObjectUtil.isNotEmpty(jsonObject.getStr("access_token"))) {
                return jsonObject.getStr("access_token");
            } else {
                throw new BaseException(BasicEnum.GET_TOKEN_ERROR);
            }
        } else {
            throw new BaseException(BasicEnum.GET_TOKEN_ERROR);
        }
    }

    private String getOpenId(String code) {
        Map<String, Object> params = new HashMap<>();
        params.put("appid", appid);
        params.put("secret", appSecret);
        params.put("js_code", code);
        params.put("grant_type", "authorization_code");

        HttpResponse response = HttpUtil.createGet(Constants.WX_OPENID_URL).form(params).execute();
        if (ObjectUtil.isNotEmpty(response.body())) {
            String body = response.body();
            JSONObject jsonObj = JSONUtil.parseObj(body);
            if (ObjectUtil.isNotEmpty(jsonObj.getInt("errcode"))) {
                throw new BaseException(BasicEnum.GET_OPENID_ERROR);
            }
            return jsonObj.getStr("openid");
        } else {
            throw new BaseException(BasicEnum.GET_OPENID_ERROR);
        }
    }
}
